
#pragma semicolon 1

#include <sourcemod>
#include <sdktools>
#include <sdktools_functions>
#include <sdktools_sound>
#include "W3SIncs/War3Source_Interface"
#include "revantools.inc"
#include <tf2>
#include <tf2_stocks>

public W3ONLY(){}

new thisRaceID;
new Handle:FriendlyFireSuicideCvar;
new Handle:SuicideDamageSentryCvar;
new Handle:MPFFCvar;
new ExplosionModel;
new bool:bSuicided[MAXPLAYERSCUSTOM];
new suicidedAsTeam[MAXPLAYERSCUSTOM];
new String:explosionSound1[]="war3source/dante/revmleko.wav";
new Float:FlameRange[]={0.0,80.0,120.0,160.0,200.0};
new FlameDamage[]={0,2,3,4,5};
new BeamSprite,BeamSprite2,BeamSpriteS,HaloSprite,HaloSpriteS;
new ToDealArrow[MAXPLAYERS];
new ArrowTarget[MAXPLAYERS];
new String:Sound1[] = { "weapons/fx/nearmiss/bulletltor03.wav"};
new String:Sound2[] = { "ambient/fire/mtov_flame2.wav"};
new String:Sound3[] = { "weapons/fx/nearmiss/bulletltor05.wav"};
new Handle:SearingArrowCh=INVALID_HANDLE;
new DamageStorm[5]={10,15,18,24,29};
new MaximumDamage[5]={15,18,24,29,30};
new Float:Chance[5]={0.00,0.20,0.25,0.28,0.30};
new Float:RadiusStorm[5]={0.00,0.20,0.25,0.28,0.30};
new bool:bIsTarget[MAXPLAYERS];
new String:catchsnd[]="npc/strider/fire.wav";
new String:ignitesnd[]="ambient/fire/gascan_ignite1.wav";
new String:burnsnd[]="ambient/explosions/explode_4.wav";
new FireSprite, Explosion, SimpleFire;
new Handle:SFXCvar;
new Float:SuicideBomberRadius[5]={0.0,222.0,333.0,444.0,555.0}; 
new Float:SuicideBomberDamage[5]={0.0,15.0,25.0,35.0,60.0};
new Float:SuicideBomberDamageTF[5]={0.0,15.0,15.0,35.0,60.0}; 
new Float:SuicideLocation[MAXPLAYERSCUSTOM][3];

new SKILL_SEAR,SKILL_FIRE,SKILL_FLAME,SKILL_SUICIDE;

public Plugin:myinfo = 
{
	name = "Race - Dante's Inferno",
	author = "MleKo",
	description = "One of the Landlord from the Hell.",
	version = "1.0",
	url = "http://strefagier.com.pl"
};

public OnPluginStart()
{
	SearingArrowCh=CreateConVar("war3_clinkz_searing_chance","0.80","Chance for Bonefletchers Searing Arrow skill.");
	SFXCvar=CreateConVar("war3_azgalor_hugefx_enable","1","Enable/Disable distracting and revealing sfx");
	FriendlyFireSuicideCvar=CreateConVar("war3_undead_suicidebomber_ff","0","Friendly fire for suicide bomber, 0 for no, 1 for yes, 2 for mp_friendlyfire");
	SuicideDamageSentryCvar=CreateConVar("war3_undead_suicidebomber_sentry","1","Should suicide bomber damage sentrys?");
	MPFFCvar=FindConVar("mp_friendlyfire");
	CreateTimer( 1.0, FlameTimer, _, TIMER_REPEAT );
	RegConsoleCmd("spriteme",cmdspriteme);
}

new glowsprite;
public Action:cmdspriteme(client,args)
{	
	new Float:endpos[3];
	War3_GetAimTraceMaxLen(client,endpos,10.0);
	TE_Start("Sprite Spray");
	TE_WriteVector("m_vecOrigin",endpos);
	TE_WriteNum("m_nModelIndex",glowsprite);
	TE_WriteFloat("m_fNoise",99.0);
	TE_WriteNum("m_nSpeed",1);
	TE_WriteNum("m_nCount",10);
	TE_SendToAll(0.0);
	PrintToConsole(client,"spriteme completed");
}

stock TE_SetupDynamicLight(const Float:vecOrigin[3], r,g,b,iExponent,Float:fRadius,Float:fTime,Float:fDecay)
{
    TE_Start("Dynamic Light");
    TE_WriteVector("m_vecOrigin",vecOrigin);
    TE_WriteNum("r",r);
    TE_WriteNum("g",g);
    TE_WriteNum("b",b);
    TE_WriteNum("exponent",iExponent);
    TE_WriteFloat("m_fRadius",fRadius);
    TE_WriteFloat("m_fTime",fTime);
    TE_WriteFloat("m_fDecay",fDecay);
}

public OnWar3LoadRaceOrItemOrdered2(num)
{
	if(num==10)
	{
	thisRaceID = War3_CreateNewRace( "Dante", "dante" );
	SKILL_FLAME=War3_AddRaceSkill(thisRaceID,"Burning Aura","Flame form Hell protects to touch Your LandLord Body .",false,4);
	SKILL_SEAR=War3_AddRaceSkill(thisRaceID,"Fire Powers","Chance to add some Fire of your Powers into your Bullets.",false,4);
	SKILL_FIRE=War3_AddRaceSkill(thisRaceID,"Inferno Fire","Calls down up to 3 waves from abyss Inferno",false,4); 
	SKILL_SUICIDE=War3_AddRaceSkill(thisRaceID,"Meltdown Inferno","When you Died, nobdy know when your Revenge Begins!",true,4); 
	War3_CreateRaceEnd( thisRaceID );
	}
}

public OnMapStart()
{
	glowsprite=PrecacheModel("sprites/strider_blackball.spr");
	glowsprite++;   //stfu
	glowsprite--;
	if(War3_GetGame()==Game_TF)
	{
		ExplosionModel=PrecacheModel("materials/particles/explosion/explosionfiresmoke.vmt",false);
		PrecacheSound("weapons/explode1.wav",false);
	}
	else
	{
	BeamSprite2=PrecacheModel("materials/sprites/fire.vmt");
	BeamSprite=PrecacheModel("materials/sprites/laser.vmt");
	HaloSprite=PrecacheModel("materials/sprites/halo01.vmt");
	War3_PrecacheSound(Sound1);
	War3_PrecacheSound(Sound2);
	War3_PrecacheSound(Sound3);
	FireSprite=PrecacheModel("effects/fire_cloud2.vmt");
	SimpleFire=PrecacheModel("sprites/flatflame.vmt");
	Explosion=PrecacheModel("sprites/floorfire4_.vmt");
	War3_PrecacheSound(catchsnd);
	War3_PrecacheSound(ignitesnd);
	War3_PrecacheSound(burnsnd);
	ExplosionModel=PrecacheModel("materials/sprites/zerogxplode.vmt",false);
	PrecacheSound("weapons/explode5.wav",false);	
	BeamSpriteS=PrecacheModel("materials/sprites/lgtning.vmt");
	HaloSpriteS=PrecacheModel("materials/sprites/halo01.vmt");
	War3_PrecacheSound(explosionSound1);
	}
}

public OnWar3EventSpawn(client)
{
	//PrintToChatAll("SPAWN %d",client);
	new race=War3_GetRace(client);
	if(race==thisRaceID)
	{
		suicidedAsTeam[client]=GetClientTeam(client);
		InitPassiveSkills(client); //sets suicide
		
	}
	else
	{
		bSuicided[client]=true; //kludge, not to allow some other race switch to this race and explode on death (ultimate)
	}
}

public OnUltimateCommand(client,race,bool:pressed)
{
	if(pressed)
	{
		if(race==thisRaceID&&IsPlayerAlive(client)&&!bSuicided[client]&&!Silenced(client))
		{
			new ult_level=War3_GetSkillLevel(client,race,SKILL_SUICIDE);
			if(ult_level>0)
			{
				suicidedAsTeam[client]=GetClientTeam(client);
				ForcePlayerSuicide(client);
			}
			else
			{
				W3MsgUltNotLeveled(client);
			}
		}
	}
}

public OnSkillLevelChanged(client,race,skill,newskilllevel)
{
	InitPassiveSkills(client);
}

public InitPassiveSkills(client)
{
	if(War3_GetRace(client)==thisRaceID)
	{
	bSuicided[client]=false;
	War3_SetBuff(client,fMaxSpeed,thisRaceID,1.5);
	}
}

public OnRaceChanged(client,oldrace,newrace)
{
	if(newrace!=thisRaceID)
	{
		War3_SetBuff(client,fMaxSpeed,thisRaceID,1.0);
		W3ResetAllBuffRace( client, thisRaceID );
	}
	else
	{
		InitPassiveSkills(client);
	}
}

//SKILL 1 ?! MLEKO !?----------------------------------------------------//
public Action:FlameTimer( Handle:timer, any:userid )
{
	if( thisRaceID > 0 )
	{
		for( new i = 1; i <= MaxClients; i++ )
		{
			if( ValidPlayer( i, true ) )
			{
				if( War3_GetRace( i ) == thisRaceID )
				{
				Flameless( i );					
				}
			}
		}
	}
}

public Flameless( client )
{
	new skill_flames = War3_GetSkillLevel( client, thisRaceID, SKILL_FLAME );
	if( skill_flames > 0 && !Hexed( client, false ) )
	{
		new Float:distance = FlameRange[skill_flames];
		new burned = FlameDamage[skill_flames];		
		new AttackerTeam = GetClientTeam( client );
		new Float:AttackerPos[3];
		new Float:VictimPos[3];		
		GetClientAbsOrigin( client, AttackerPos );		
		AttackerPos[2] += 40.0;
		for( new i = 1; i <= MaxClients; i++ )
		{
			if( ValidPlayer( i, true ) && GetClientTeam( i ) != AttackerTeam && !W3HasImmunity( i, Immunity_Skills ) )
				{				
				GetClientAbsOrigin( i, VictimPos );
				VictimPos[2] += 40.0;				
				if( GetVectorDistance( AttackerPos, VictimPos ) <= distance )
				{
					War3_DealDamage(i,burned,client,DMG_ENERGYBEAM,"Burn Mother Fucker",W3DMGORIGIN_SKILL);					
					IgniteEntity(i, 2.0);
				}
			}
		}
	}
}


//SKILL 2 ?! MLEKO !?----------------------------------------------------//
public bool:FireArrow(const attacker,const victim,Float:delay,damage,bool:searingfire){
	if(ValidPlayer( attacker, true )&&ValidPlayer( victim, true ))
	{
		ToDealArrow[attacker]=damage;
		ArrowTarget[attacker]=victim;
		new Float:start_pos[3];
		new Float:target_pos[3];
		GetClientAbsOrigin(attacker,start_pos);
		GetClientAbsOrigin(victim,target_pos);
		target_pos[2]+=40.0;
		start_pos[2]+=45.0;
		
		start_pos[0] += GetRandomFloat( -38.0, 38.0 );
		start_pos[1] += GetRandomFloat( -38.0, 38.0 );
		if(searingfire==false)
		{
			new Float:FatTony = GetRandomFloat(1.0,2.8);
			TE_SetupBeamPoints(start_pos, target_pos, BeamSprite, HaloSprite, 0, 10, GetRandomFloat(0.8,1.4), FatTony, FatTony, 0, 4.5, {255,205,25,255}, 100);
			TE_SendToAll(delay);
		}
		else
		{
			TE_SetupBeamPoints(start_pos, target_pos, BeamSprite2, HaloSprite, 0, 80, GetRandomFloat(0.8,1.4), 1.35, 1.6, 0, 4.5, {255,255,255,255}, 100);
			TE_SendToAll(delay);
		}
		if(damage>0)
		{
			CreateTimer(delay,Timer_DealDamage,attacker);
		}
		else {
			EmitSoundToAll(Sound1,victim);
			EmitSoundToAll(Sound1,attacker);
		}
		return true;
	}
	return false;
}

public Action:Timer_DealDamage(Handle:t,any:attacker)
{
	if(ValidPlayer(attacker,true))
	{
		new victim = ArrowTarget[attacker];
		if(ValidPlayer(victim,true))
		{
			new damage = ToDealArrow[attacker];
			War3_DealDamage( victim, damage, attacker, DMG_BULLET, "Powers" );
			PrintHintText(victim,"Dealt +%i damage to your victim",damage);
			EmitSoundToAll(Sound1,victim);
			EmitSoundToAll(Sound1,attacker);
		}
	}
}

public OnW3TakeDmgBullet(victim,attacker,Float:damage)//OnWar3EventPostHurt( victim, attacker, damage )
{
	if( W3GetDamageIsBullet() && ValidPlayer( victim, true ) && ValidPlayer( attacker, true ) && GetClientTeam( victim ) != GetClientTeam( attacker ) )
	{
		if( War3_GetRace( attacker ) == thisRaceID && !W3HasImmunity(victim,Immunity_Skills) && !Hexed( attacker, false ))
		{
			new skill_dmg = War3_GetSkillLevel( attacker, thisRaceID, SKILL_SEAR );
			if(skill_dmg > 0)
			{
				if( GetRandomFloat( 0.0, 1.0 ) <= GetConVarFloat(SearingArrowCh) )
				{
					new String:wpnstr[32];
					GetClientWeapon( attacker, wpnstr, 32 );
					if(!StrEqual( wpnstr, "wep_knife" ) )
					{
						if(FireArrow(attacker,victim,0.2,0,true))
						{
							new damageamount = GetRandomInt(3,5);
							FireArrow(attacker,victim,1.8,0,true);
							EmitSoundToAll(Sound2,victim);
							EmitSoundToAll(Sound3,attacker);
							War3_DealDamage( victim, damageamount, attacker, DMG_BULLET, "Fire_Powers" );
							PrintCenterText(attacker,"Fire Powers dealt +%i damage!",damageamount);
						}
					}
				}
			}
		}
	}
	if(IS_PLAYER(victim)&&IS_PLAYER(attacker)&&victim>0&&attacker>0&&attacker!=victim)
	{
		new vteam=GetClientTeam(victim);
		new ateam=GetClientTeam(attacker);
		if(vteam!=ateam)
		{
			new race_attacker=War3_GetRace(attacker);
			new skill_level=War3_GetSkillLevel(attacker,thisRaceID,SKILL_FIRE);
			if(race_attacker==thisRaceID && skill_level>0 )
			{
				if(GetRandomFloat(0.0,1.0)<=Chance[skill_level] && !W3HasImmunity(victim,Immunity_Skills))
				{
					new Float:spos[3];
					new Float:epos[3];
					GetClientAbsOrigin(victim,epos);
					GetClientAbsOrigin(attacker,spos);
					epos[2]+=35;
					spos[2]+=100;
					if(GetConVarBool(SFXCvar))
					{
						TE_SetupBeamPoints(spos, epos, BeamSprite, BeamSprite, 0, 35, 1.0, 10.0, 10.0, 0, 10.0, {255,25,25,255}, 30);
						TE_SendToAll();
					}
					new damage1=DamageStorm[skill_level];
					new damage2=MaximumDamage[skill_level];
					new Float:radius=RadiusStorm[skill_level];
					DoFire(attacker,victim,radius,damage1,damage2,true);
					
					W3FlashScreen(victim,RGBA_COLOR_RED);
				
					//bIsTarget[victim]=true;
					CreateTimer( 0.10, Timer_DeSelect, victim );

					EmitSoundToAll(burnsnd,victim);
					//PrintHintText(attacker,"Fire Storm");
				}
			}
		}
	}
}


// MLEKO 3 FIRESTORM ?!?----------------------------------------------------//
public DoFire(attacker,victim,Float:radius,damage,maxdmg,bool:showmsg)
{
	if(ValidPlayer(victim,true)&&ValidPlayer(attacker,true)){
		//if(IsPlayerAlive(victim)&&IsPlayerAlive(attacker));
		//{
			if(War3_GetRace(attacker)==thisRaceID && War3_GetRace(victim)!=War3_GetRaceIDByShortname("dante"))
			{
				new Float:StartPos[3];
				new Float:EndPos[3];
				
				GetClientAbsOrigin( attacker, StartPos );
				GetClientAbsOrigin( victim, EndPos );

				StartPos[2]+=100;
				TE_SetupGlowSprite(StartPos,FireSprite,3.0,0.80,212);
				TE_SendToAll();
				TE_SetupBeamRingPoint(StartPos,74.0,76.0,HaloSprite,HaloSprite,0,15,3.45,100.0,2.0,{255,77,77,255},0,0);
				TE_SendToAll();
				TE_SetupDynamicLight(StartPos,255,80,80,10,radius,3.30,2.2);
				TE_SendToAll();
				W3FlashScreen(attacker,RGBA_COLOR_RED);
				EmitSoundToClient(attacker, catchsnd);				
				new waveammount = GetRandomInt(1,3);
				if(waveammount!=0)
				{
					DoExplosion(damage,maxdmg,attacker,victim);
				}
				if(waveammount==2)
				{
					DoExplosion(damage,maxdmg,attacker,victim);
				}
				if(waveammount==3)
				{
					DoExplosion(damage,maxdmg,attacker,victim);
				}
				if(showmsg)
				{
					PrintHintText(attacker,"Inferno Fire:\nCasted %i Fire Ball",waveammount);
				}
			}
		//}
	}
}

public DoExplosion(magnitude,maxdmg,client,target)
{
	new Float:Destination[3];
	GetClientAbsOrigin(client,Destination);
	new AttackerTeam = GetClientTeam(client);
	TE_SetupBeamRingPoint(Destination,1.0,1000.0,HaloSprite,HaloSprite,0,15,2.8,10.0,2.0,{255,120,120,255},0,0);
	TE_SendToAll();
	War3_DealDamage(target,3,client,DMG_BULLET,"Inferno Fire");
	for(new i=1;i<=MaxClients;i++)
		{
			if(ValidPlayer(i,true) && GetClientTeam(i)!=AttackerTeam && !bIsTarget[i])
			{
				bIsTarget[i]=true;
				CreateTimer( 0.10, Timer_DeSelect, i );
				new Float:Vec[3];
				GetClientAbsOrigin(target,Vec);
				new Float:Origin[3];
				GetClientAbsOrigin(i,Origin);
				Vec[0] += GetRandomFloat( -150.0, 150.0 );
				Vec[1] += GetRandomFloat( -150.0, 150.0 );
				Vec[2] += 10.0;
				if(GetConVarBool(SFXCvar))
				{
					TE_SetupExplosion(Vec, Explosion, 6.5, 1, 4, 0, 0);
					TE_SendToAll();
					TE_SetupExplosion(Vec, Explosion, 6.5, 1, 4, 0, 0);
					TE_SendToAll(0.18);
					Destination[2] += 100.0;
					TE_SetupBeamPoints( Vec, Destination, BeamSprite, HaloSprite, 0, 1, 0.61, 20.0, 2.0, 0, 1.0, { 255, 11, 11, 255 }, 1 );
					TE_SendToAll();
				}
				if(GetVectorDistance(Origin,Vec) < 100.0)
				{
					new magdmg = GetRandomInt(magnitude,maxdmg);
					PrintToConsole(client,"Inferno Fire hit a target and damaged him for %d damage",magdmg);
					IgniteEntity(i, 2.0);
					EmitSoundToClient(i, ignitesnd);
					W3FlashScreen(i,RGBA_COLOR_RED);
					War3_ShakeScreen(i);
					//TODO 1 - may add explosion sounds?
					War3_DealDamage(i,magdmg,client,DMG_BULLET,"Inferno Fire");
					PrintToConsole(i,"hit by a Fire from Hell");
					PrintCenterText(client,"Inferno Fire was successfully");
				}
			}
		}
}
//S3
public IgniteExplosion(mindmg,maxdmg,client,target)
{
	new Float:Destination[3];
	GetClientAbsOrigin(target,Destination);
	new AttackerTeam = GetClientTeam(client);
	EmitSoundToClient(client, catchsnd);
	for(new i=1;i<=MaxClients;i++)
		{
			if(ValidPlayer(i,true)&&GetClientTeam(i)!=AttackerTeam && !bIsTarget[i])
			{
				new Float:Vec[3];
				GetClientAbsOrigin(i,Vec);
				if(GetVectorDistance(Destination,Vec)<=110.0)
				{
					bIsTarget[i]=true;
					CreateTimer( 0.10, Timer_DeSelect, i );
					//new Float:dir[3]={0.0,0.0,-90.0};
					new magdmg = GetRandomInt(mindmg,maxdmg);
					PrintToConsole(client,"Inferno Fire dealing %i damage",magdmg);
					PrintToChat(i,"\x05Hit by Fire from Hell");
					IgniteEntity(i, 2.0);
					W3FlashScreen(i,RGBA_COLOR_RED);
					War3_ShakeScreen(i);
					//TODO 1 - may add explosion sounds?
					War3_DealDamage(i,magdmg,client,DMG_BULLET,"Inferno Fire");
					if(GetConVarBool(SFXCvar))
					{
						TE_SetupExplosion(Vec, Explosion, 6.5, 1, 4, 0, 0);
						TE_SendToAll();
						TE_SetupBeamRingPoint( Vec,65.0,75.0,HaloSprite,HaloSprite,0,15,12.20,100.0,2.0,{255,0,0,255},30,0);
						TE_SendToAll();
						TE_SetupBeamRingPoint( Vec,74.0,150.0,SimpleFire,HaloSprite,0,15,3.45,20.0,2.0,{255,0,0,255},0,0);
						TE_SendToAll();
					}
				}
			}
		}
}
//S3
public Action:Timer_DeSelect(Handle:timer, any:client)
{
	if(ValidPlayer(client,true))
	{
		bIsTarget[client]=false;
	}
}
//S4
public SuicideBomber(client,level)
{
	if(suicidedAsTeam[client]!=GetClientTeam(client))
	{
		return; //switched team
	}
	new Float:radius=SuicideBomberRadius[level];
	if(level<=0)
		return; // just a safety check
	new ss_ff=GetConVarInt(FriendlyFireSuicideCvar);
	new bool:mp_ff=GetConVarBool(MPFFCvar);
	new our_team=GetClientTeam(client); 
	new Float:client_location[3];
	for(new i=0;i<3;i++)
	{
		client_location[i]=SuicideLocation[client][i];
	}
	
	
	TE_SetupExplosion(client_location,ExplosionModel,10.0,1,0,RoundToFloor(radius),160);
	TE_SendToAll();
	
	if(War3_GetGame()==Game_TF)
	{
	

		ThrowAwayParticle("ExplosionCore_buildings", client_location,  5.0);
		ThrowAwayParticle("ExplosionCore_MidAir", client_location,  5.0);
		ThrowAwayParticle("ExplosionCore_MidAir_underwater", client_location,  5.0);
		ThrowAwayParticle("ExplosionCore_sapperdestroyed", client_location,  5.0);
		ThrowAwayParticle("ExplosionCore_Wall", client_location,  5.0);
		ThrowAwayParticle("ExplosionCore_Wall_underwater", client_location,  5.0);
	}
	else
	{
		client_location[2]-=40.0;
	}
	
	TE_SetupBeamRingPoint(client_location, 10.0, radius, BeamSpriteS, HaloSpriteS, 0, 35, 2.55, 33.0, 50.0, {255,0,0,255}, 100, 0);
	TE_SendToAll();
	//TE_SetupBeamRingPoint(const Float:center[3], Float:Start_Radius, Float:End_Radius, ModelIndex, HaloIndex, StartFrame, 
	//FrameRate, Float:Life, Float:Width, Float:Amplitude, const Color[4], Speed, Flags)
	
	if(War3_GetGame()==Game_TF)
	{
		client_location[2]-=30.0;
	}
	else
	{
		client_location[2]+=40.0;
	}
	
	EmitSoundToAll(explosionSound1,client);
	
	if(War3_GetGame()==Game_TF)
	{
		EmitSoundToAll("weapons/explode1.wav",client);
	}
	else
	{
		EmitSoundToAll("weapons/explode5.wav",client);
	}
	
	///building damage
	if(War3_GetGame()==Game_TF && GetConVarBool(SuicideDamageSentryCvar))
	{
		// Do they have a sentry that should get blasted too?
		new ent=0;
		
		new buildinglist[1000];
		new buildingsfound=0;
		
		while((ent = FindEntityByClassname(ent,"obj_sentrygun"))>0)
		{
			buildinglist[buildingsfound]=ent;
			buildingsfound++;
		}
		while((ent = FindEntityByClassname(ent,"obj_teleport"))>0)
		{
			buildinglist[buildingsfound]=ent;
			buildingsfound++;
		}
		while((ent = FindEntityByClassname(ent,"obj_dispenser"))>0)
		{
			buildinglist[buildingsfound]=ent;
			buildingsfound++;
		}

		for(new i=0;i<buildingsfound;i++)
		{
			ent=buildinglist[i];
			if(!IsValidEdict(ent)) continue;
			new builder=GetEntPropEnt(ent,Prop_Send,"m_hBuilder");
			if(GetClientTeam(builder)!=our_team)
			{
				new Float:pos_comp[3];
				GetEntPropVector(ent,Prop_Send,"m_vecOrigin",pos_comp);
				new Float:dist=GetVectorDistance(client_location,pos_comp);
				if(dist>radius)
					continue;
				
				if(!W3HasImmunity(builder,Immunity_Ultimates))
				{
					//new damage=RoundFloat(100*(1-FloatDiv(dist,radius)+0.40));
					new damage=RoundFloat(SuicideBomberDamageTF[level]*(radius-dist)/radius); //special case
					
					PrintToConsole(client,"%T","Suicide bomber BUILDING damage: {amount} at distance {amount}",client,damage,dist);
					
					SetVariantInt(damage);
					AcceptEntityInput(ent,"RemoveHealth",client); // last parameter should make death messages work
				}
				else
				{
					PrintToConsole(client,"%T","Player {player} has immunity (protecting buildings)",client,builder);
				}
			}
		}
	}
	
	new Float:location_check[3];
	for(new x=1;x<=MaxClients;x++)
	{
		if(ValidPlayer(x,true)&&client!=x)
		{
			new team=GetClientTeam(x);
			if(ss_ff==0 && team==our_team)
			continue;
			else if(ss_ff==2 && !mp_ff && team==our_team)
			continue;

			GetClientAbsOrigin(x,location_check);
			new Float:distance=GetVectorDistance(client_location,location_check);
			if(distance>radius)
			continue;
			
			if(!W3HasImmunity(x,Immunity_Ultimates))
			{
				new Float:factor=(radius-distance)/radius;
				new damage;
				if(War3_GetGame()==Game_TF)
				{
				damage=RoundFloat(SuicideBomberDamageTF[level]*factor);
				}
				else
				{
				damage=RoundFloat(SuicideBomberDamage[level]*factor);
				}
				War3_DealDamage(x,damage,client,_,"Dante Revenge",W3DMGORIGIN_ULTIMATE,W3DMGTYPE_PHYSICAL);
				W3PrintSkillDmgConsole(x,client,War3_GetWar3DamageDealt(),SKILL_SUICIDE);
				War3_ShakeScreen(x,3.0*factor,250.0*factor,30.0);
				W3FlashScreen(x,RGBA_COLOR_RED);
				IgniteEntity(x, 6.0);
			}
			else
			{
				PrintToConsole(client,"%T","Could not damage player {player} due to immunity",client,x);
			}
			
		}
	}
}

public OnWar3EventDeath(victim,attacker)
{
	if(!bSuicided[victim])
	{
		new race=War3_GetRace(victim);
		new skill=War3_GetSkillLevel(victim,thisRaceID,SKILL_SUICIDE);
		if(race==thisRaceID && skill>0 && !Hexed(victim))
		{
			bSuicided[victim]=true;
			//suicidedAsTeam[victim]=GetClientTeam(victim); 
			GetClientAbsOrigin(victim,SuicideLocation[victim]);
			CreateTimer(2.5,DelayedBomber,victim);
		}
	}
}
public Action:DelayedBomber(Handle:h,any:client)
{
	new level=War3_GetSkillLevel(client,thisRaceID,SKILL_SUICIDE);
	if(level>0&&ValidPlayer(client)&&!IsPlayerAlive(client))
	{
		if(!W3Denied(DN_Suicide,client))
		{
			SuicideBomber(client,War3_GetSkillLevel(client,thisRaceID,SKILL_SUICIDE));
		}
	}
	else
	{
		bSuicided[client]=false;
	}
}